export { }
/**
 * 接口一方面可以在面向对象变成中表示行为的抽象  另一方面可以描述对象的形状
 * 接口就是把一些类中共有的属性和方法抽象出来，可以用来约束实现此接口的类
 * 一个类可以继承另一个类并实现多个接口
 * 接口像插件一样是用来增强类的，而抽象类是具体类的抽象概念
 * 一个类可以实现多个接口，一个接口也可以被多个类实现，但一个类可以有多个子类 但只能有一个父类
 */

namespace a {
  // 描述对象的形状
  interface Speakable {
    name: string
    speak(): void
  }
  let speakMan: Speakable = {
    name: 'smd',
    speak: () => {

    }
  }

  // 行为的抽象
  interface Speakable { // 同名接口可以写多个，类型会自动合并
    speak(): void
  }
  interface Eatable {
    eat(): void
  }

  class Person implements Speakable, Eatable { // 类可以实现接口 必须实现接口中所有的方法与属性
    name: string
    speak(): void {

    }
    eat(): void {

    }
  }
}

// 任意属性
interface Person2 {
  readonly id: number
  name: string
  [key: string]: any // 在不知道的情况下  key值为字符串  值为any
}

let p: Person2 = {
  id: 0,
  name: "smd",
  age: 18
}

// 接口的继承
interface Speakable2 {
  speak(): void
}
interface SpeakChinese extends Speakable2 {
  speakChinese(): void
}

class ChineseMan implements SpeakChinese {
  speakChinese() {
  }
  speak(): void {
  }
}

interface Person3 {
  readonly id: number
}
let p3: Person3 = {
  id: 1
}
// 报错 p3.id = 1

// 函数类型接口
interface Discount {
  (price: number): number
}
let discount: Discount = (price: number): number => {
  return 0.9 * price
}
discount(100)

// 可索引接口
interface User { // 既可以对数组约束  又可以对对象约束
  [index: number]: string
}
let user = {
  1: '1'
}
let arr = ['1']

// 描述构造函数类型的接口
class Animal {
  constructor(public name: string) {

  }
}
interface withNameClass {
  new(name: string): any // () 表示函数  前边加上new  表示构造函数
}
function createClass(clazz: withNameClass, name: string) {
  return new clazz(name)
}

let anm = createClass(Animal, 'cat')
console.log(anm.name) // cat

/**
 * interface 中 描述函数的new关键字必须添加
 * 当创建一个类的时候  会得到两个类型
 * 1.构造函数的函数类型
 * 2.类的实例类型
 */
namespace a {
  class Component {
    static myName: string = '静态名称属性'
    myName: string = '实例名称属性'
  }
  // Component类名本身表示实例的类型
  let c: Component = new Component()
  let f: typeof Component = Component // 等号后边的 Component在此处是值
}
namespace b {
  function Component() {
    this.myName = '实例名称属性'
  }
  Component.myName = '静态名称属性'
}
/**
 * 综上 如果interface 中没有new  则描述的是一个函数
 */
namespace c {
  class Animal {
    constructor(public name: string) {

    }
  }
  interface withNameClass {
    (name: string): any // () 表示函数  前边加上new  表示构造函数
  }

  let wc: withNameClass = (name: string) => { }
  // function createClass(clazz: withNameClass, name: string) {
  //   return new clazz(name)
  // }

  // let anm = createClass(Animal, 'cat')
  // console.log(anm.name) // cat
}

/**
 * 但是如果加上new 则就是类的构造函数
 */
namespace c {
  class Animal {
    constructor(public name: string) {

    }
  }
  interface withNameClass {
    new(name: string): any // () 表示函数  前边加上new  表示构造函数
  }

  let wc: withNameClass = Animal
  // function createClass(clazz: withNameClass, name: string) {
  //   return new clazz(name)
  // }

  // let anm = createClass(Animal, 'cat')
  // console.log(anm.name) // cat
}

// -------
// 描述函数与方法
interface Type1 { // 描述函数
  (name: string): void
}
interface Type2 { // 描述对象中的属性
  a: (name: string) => any
}
let t1: Type1 = (name: string) => { }
let t2: Type2 = {
  a: t1
}

// 既描述函数  又包括属性
interface Type3 {
  (name: string): void
  age: number
}
let t3: any = (name: string) => { }
t3.age = 12
let t4: Type3 = t3